// handle.go
package restsrv

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"

	//bind "soc/bind"
	"time"
)

/*
 200 ok  - 成功返回状态，对应，GET,PUT,PATCH,DELETE.
 201 created  - 成功创建。
 304 not modified   - HTTP缓存有效。
 400 bad request   - 请求格式错误。
 401 unauthorized   - 未授权。
 403 forbidden   - 鉴权成功，但是该用户没有权限。
 404 not found - 请求的资源不存在
 405 method not allowed - 该http方法不被允许。
 410 gone -  url对应的资源现在不可用。
 415 unsupported media type - 请求类型错误。
 422 unprocessable entity - 校验错误时用。
 429 too many request - 请求过多。
*/

/*
响应码，000000表示成功
失败：
108100 解析失败-入参错误
108101 应用Id不存在
108102 消息队列已满
108103 呼叫资源不足
108104 其他错误
108105 callid 不存在
*/

const (
	webRetCodeSuccess        = "000000"
	webRetCodeParamFailed    = "108100"
	webRetCodeAppidNotExist  = "108101"
	webRetCodeMqIsFull       = "108102"
	webRetCodeOutOfLine      = "108103"
	webRetCodeSystemWrong    = "108104"
	webRetCodeCallIdNotExist = "108105"
	webRetCodeCommandDelay   = "108106"
	recvMaxByte              = 1048576 //1024*1024 1m
)

var (
	errCall        int = 0
	CallType       string
	CustermorNumer string
	AnswerType     string = ""
	count          int
	TestVoice      string
	aiflag         bool
	checkPassWord  int
	debug          bool = true
)

func DebugOff() {
	debug = false
}

func DebugOn() {
	debug = true
}

func SetAnswerType(anserType string) {
	AnswerType = anserType
}

func SetAnswerTypeDefault() {
	AnswerType = ""
}

func SetAnswerTypeYuyin() {
	AnswerType = "yuyin"
}

func SetAnswerTypertm() {
	AnswerType = "rtm"
}

func SetAnswerTypeNotts() {
	AnswerType = "notts"
}

func SetAnswerTypeTts() {
	AnswerType = "tts"
}

type rptReply struct {
	RetCode string `json:"code"`
	Msg     string `json:"msg"`
}

func systemfailed(w http.ResponseWriter, webCode int, ret string, appid string, callid string) {

	res := jsonResult{ret, appid, callid}

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(webCode) // unprocessable entity
	if err := json.NewEncoder(w).Encode(res); err != nil {
		fmt.Println("json failed", err)
		return
	}
}

func responseSuccess(w http.ResponseWriter) {
	//返回结果
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)

	res := rptReply{"000000", "success"}

	if err := json.NewEncoder(w).Encode(res); err != nil {
		fmt.Println("outCall send failed!", err)
	}
}

func eventProcess(event Normal, msg []byte) {

	if debug {
		fmt.Println("recv eventProcess event:", event)
	}
	callId = event.Callid

	switch event.Event {
	case "callstatrpt":
		var status callstatus
		json.Unmarshal(msg, &status)

		if 1 == status.AnsCode {

			if value, ok := Callist.Load(event.Callid); ok {
				v := value.(*callstat)

				v.answerTime = time.Now()
				if v.answerTime.Unix()-v.startTime.Unix() > 10 {
					errCall++

					fmt.Printf("call start at:%ld,answer at:%ld\n", v.startTime.Unix(), v.answerTime.Unix())
					fmt.Printf("eventProcess call is time out %v, err call number:%v!\n", event, errCall)

					break
				}

				value.(*callstat).status = "ring"
				value.(*callstat).ringTime = time.Now()

			} else {
				fmt.Println("call is not exist!", event)
			}
		} else if 2 == status.AnsCode {

			if CallType == "callback" {
				//三方通话测试
				if status.Dir == 1 {
					go func() {
						time.Sleep(2 * time.Second)
						//TestThreeWay(event.Appid, "12345678", event.Callid)
					}()
				}
				return
			}

			if AnswerType == "yuyin" {
				testMultApiNewVoice(event.Appid, event.Callid)
			} else if AnswerType == "tts" {
				testMultApiAllTTS(event.Appid, event.Callid)
			} else if AnswerType == "rtm" {
				testMultApiTtsRtm(event.Appid, event.Callid)

			} else if AnswerType == "notts" {
				testMultApiNoTTS(event.Appid, event.Callid)
			} else {
				testMultApi(event.Appid, event.Callid)

			}

			stat, ok := Callist.Load(status.Callid)
			if ok {
				stat.(*callstat).status = "answer"
				stat.(*callstat).answerTime = time.Now()
			} else {
				fmt.Printf("%s is not fond!\n", status.Callid)
			}

		} else {
			if stat, ok := Callist.Load(status.Callid); ok {
				stat.(*callstat).status = "error"
			} else {
				fmt.Printf("%s is not fond!\n", status.Callid)
			}

			fmt.Printf("[%v]number[%v] is not answer:%d,sipCode:%v!\n", status.Callid,
				status.Number, status.AnsCode, status.SipCode)
		}
	case "playoverrpt":
		break
		fmt.Println("eventProcess playoverrpt break", count)

		if 0 == count {
			testGetDTMFWithTTS(event.Appid, event.Callid)

			count++
		} else if 1 == count {
			testPlayFile(event.Appid, event.Callid, "test.wav")
			count++
		} else {
			testHungup(event.Appid, event.Callid)

		}
	case "ivrreportdtmf":

		var res DtmfRpt
		err := json.Unmarshal(msg, &res)
		if nil != err {
			fmt.Println("按键上报通知,格式不正确", err)
		}

		fmt.Printf("eventProcess ivrreportdtmf recv dtmf:%s\n", res.Dtmf)
		if len(res.ServiceId) > 0 {

			if "99#" == res.Dtmf {
				testPlayTTSInCall(res.Appid, res.Callid, "both", "请输入您的验证码", 1)
				checkPassWord = 1
			} else if "33#" == res.Dtmf {

				TestThreeWay(event.Appid, "12345678", event.Callid)
			} else if "44#" == res.Dtmf {
				TestReplaceRobot(event.Appid, event.Callid)
			}

		} else {

			if checkPassWord == 1 || checkPassWord == 3 {
				if "8888#" == res.Dtmf {
					if CallType == "callback" {
						testPlayTTSInCall(res.Appid, res.Callid, "both", "验证通过", 0)
						checkPassWord = 2
					}
				} else if checkPassWord == 1 {
					testPlayTTSInCall(res.Appid, res.Callid, "both", "您输入的密码不正确,请重试", 1)
					checkPassWord = 3
				}
			} else {

				if "520#" == res.Dtmf {
					testTransfer(event.Appid, event.Callid)

				} else if "888#" == res.Dtmf {
					testLeavMessage(event.Appid, event.Callid)
					testHungup(event.Appid, event.Callid)

				} else {

					testHungup(event.Appid, event.Callid)
				}
			}
		}

	case "multrpt":
		if CallType == "callback" {
			return
		}

		var rpt Multrpt
		err := json.Unmarshal(msg, &rpt)
		if err == nil {
			if len(rpt.Hungup) > 0 || rpt.Status == 1 {
				stat, ok := Callist.Load(rpt.CallId)
				if ok {
					stat.(*callstat).status = "finish"
					stat.(*callstat).hunTime = time.Now()
				} else {
					fmt.Printf("%s is not fond!\n", rpt.CallId)
				}
			}
		}

		testGetDTMFWithTTSex(event.Appid, event.Callid)

	case "incomingcall":

		//bind.BindXnumber("02260624205", "13120496587", "18898565822")

		testAnswerCall(event.Appid, event.Callid)
	case "incomingcallack":
		fmt.Println("time now:", time.Now().String())
		//time.Sleep(1 * time.Second)

		testTransfer(event.Appid, event.Callid)
		//testGetDTMFWithTTS(event.Appid, event.Callid)
	case "callleaveendrpt":
		testHungup(event.Appid, event.Callid)
	case "calldisconnectrpt":
		var call hungerrpt
		json.Unmarshal(msg, &call)
		if 0 == call.Dir && call.Number == "612345678" {
			testHungup(event.Appid, event.Callid)
		}

		stat, ok := Callist.Load(call.Callid)
		if ok {
			stat.(*callstat).status = "finish"
			stat.(*callstat).hunTime = time.Now()
		} else {
			fmt.Printf("%s is not fond!\n", call.Callid)
		}

		if call.Reason != 0 {
			errCall++
			fmt.Printf("err finished:%s :%2d\n", call.Callid, call.Reason)
		}
	default:
		fmt.Errorf("错误的事件类型:%v", string(msg))
	}

}

func SrvMainHandle(w http.ResponseWriter, r *http.Request) {

	var report Normal

	body, err := ioutil.ReadAll(io.LimitReader(r.Body, recvMaxByte))
	if err != nil {
		fmt.Println("outCall recv from request error", err)
		systemfailed(w, 422, webRetCodeSystemWrong, "", "")
		return
	}

	if debug {
		fmt.Println("recv report:", string(body))
	}

	responseSuccess(w)

	if err := r.Body.Close(); err != nil {
		fmt.Println("outCall recv from request error", err)
		systemfailed(w, 422, webRetCodeSystemWrong, "", "")
		return
	}

	if err := json.Unmarshal(body, &report); err != nil {
		fmt.Println("outCall recv msg parse failed", err)
		systemfailed(w, 200, webRetCodeSystemWrong, "", "")
		return
	}

	go eventProcess(report, body)

}

func TestReplcaeHandle(w http.ResponseWriter, r *http.Request) {

	TestReplaceRobot(testAppId, callId)
}

func TestMonitorHandle(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	number := r.FormValue("number")

	TestThreeWay(testAppId, number, callId)
}
